package com.xuecheng.media.service.jobhandler;

import com.xuecheng.base.utils.Mp4VideoUtil;
import com.xuecheng.media.model.po.MediaProcess;
import com.xuecheng.media.service.MediaFileProcessService;
import com.xuecheng.media.service.MediaFileService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class videoTask {

    @Autowired
    private MediaFileProcessService mediaFileProcessService;

    @Value("${videoprocess.ffmpegpath}")
    private String ffmpegPath;

    @Autowired
    private MediaFileService mediaFileService;

    /**
     * 2、视频处理任务
     */
    @XxlJob("videoJobHandler")
    public void shardingJobHandler() throws Exception {

        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex(); //执行器的序号
        int shardTotal = XxlJobHelper.getShardTotal(); //执行器的总数

        //查询任务
        List<MediaProcess> mediaProcessList = mediaFileProcessService.getMediaProcessList(shardTotal, shardIndex, 5);

        //任务数量
        int size = mediaProcessList.size();
        log.debug("取到视频处理任务数:" + size);
        if(size <= 0){
            return;
        }

        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(size);
        //使用计数器
        CountDownLatch countDownLatch = new CountDownLatch(size);
        mediaProcessList.forEach(mediaProcess -> {
            //将任务加入线程池
            executorService.execute(() -> {
                try {
                    //任务id
                    Long taskId = mediaProcess.getId();

                    //文件id就是md5
                    String fileId = mediaProcess.getFileId();

                    //开启任务
                    boolean b = mediaFileProcessService.startTask(taskId);
                    if(!b){
                        log.debug("抢占任务失败，任务id:{}", taskId);
                        return;
                    }
                    log.debug("开始执行任务:{}", mediaProcess);
                    //桶
                    String bucket = mediaProcess.getBucket();

                    //objectName
                    String objectName = mediaProcess.getFilePath();

                    //下载minio视频到本地
                    File file = mediaFileService.downloadFileFromMinIO(bucket, objectName);
                    if(file == null){
                        log.debug("下载视频出错，taskId:{},bucket:{},objectName:{}", taskId, bucket, objectName);
                        //保存任务处理失败的结果
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "下载视频到本地失败");
                        return;
                    }

                    //源avi视频的路径
                    String video_path = file.getAbsolutePath();

                    //转换后mp4文件的名称
                    String mp4_name = fileId + ".mp4";

                    //转换后mp4文件的路径
                    //创建一个临时文件，作为转换后的文件
                    File mp4File = null;
                    try {
                        mp4File = File.createTempFile("minio", ".mp4");
                    } catch (IOException e) {
                        log.debug("创建临时文件异常:{}", e.getMessage());
                        //保存任务处理失败的结果
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "创建临时文件异常");
                        return;
                    }

                    String mp4_path = mp4File.getAbsolutePath();
                    //创建工具类对象
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegPath,video_path,mp4_name,mp4_path);

                    //开始视频转换，成功将返回success
                    String result = videoUtil.generateMp4();

                    //不成功
                    if(!result.equals("success")){
                        log.debug("视频转码失败，原因:{},bucket:{},objectName:{}", result, bucket, objectName);
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, result);
                        return;
                    }

                    //成功，上传到minio
                    System.out.println("zzzzzzzzzzzzzzzzzzzzzzzzz" + objectName);
                    String[] split = objectName.split("\\.");
                    String new_objectName = split[0] + ".mp4";
                    boolean b1 = mediaFileService.addMediaFilesToMinIo(mp4File.getAbsolutePath(), "video/mp4", bucket, new_objectName);
                    if(!b1){
                        log.debug("上传mp4到minio失败,taskId:{}", taskId);
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "上传mp4到minio失败");
                        return;
                    }

                    //mp4文件的url拼装
                    String url = getFilePathByMd5(fileId, ".mp4");

                    //更新任务状态为成功，修改任务状态
                    mediaFileProcessService.saveProcessFinishStatus(taskId, "2", fileId, url, "保存任务成功");
                } finally {
                    //计数器减一
                    countDownLatch.countDown();
                }


            });
        });

        //阻塞,指定一个最大限度的等待时间
        countDownLatch.await(30, TimeUnit.MINUTES);
    }

    private String getFilePathByMd5(String fileMd5, String fileExt){
        return fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" + fileMd5 + fileExt;
    }

}
